<?php

/**
 * 等额本金、等额本息利率计算
 */

namespace loan;

class RateCount {

    /**
     * 等额本息计算
     * @param $money 贷款总金额
     * @param $rate 基准利率即年利率
     * @param $stage 贷款期数：1年12期
     * @return array
     */
    public static function interest($money, $rate, $stage) {
        $monthRate = static::monthRate($rate);
        $info = [];
        $total = $capitalMoneyTotal = $firstMoney = $interestTotal = 0;
        for ($i = 1; $i <= $stage; ++$i) {
            list($monthMoney, $interestMoney, $capitalMoney) = static::interestInfo($money, $monthRate, $stage, $i);
            $total += $monthMoney;
            $interestTotal += $interestMoney;
            $capitalMoneyTotal += $capitalMoney;
            $info[] = [
                'stage'           => (string)$i, // 期数
                'month_money'     => money_mil($monthMoney), // 月供总额
                'capital_money'   => money_mil($capitalMoney), // 月供本金
                'interest_money'  => money_mil($interestMoney), // 月供利息
                'surplus_capital' => money_mil(round($money - $capitalMoneyTotal, 2)), // 剩余本金
            ];

            $i == 1 && $firstMoney = (string)$monthMoney;
        }

        $total = (string)round($total / 10000, 2);
        $interestTotal = (string)round($interestTotal / 10000, 2);
        return compact('total', 'interestTotal', 'info', 'firstMoney');
    }

    // 等额本金计算
    public static function capital($money, $rate, $stage) {
        // 月利率
        $monthRate = static::monthRate($rate);

        // 每月应还本金
        $capitalMoney = round($money / $stage, 2);

        $total = $firstMoney = $interestTotal = $capitalMoneyTotal = 0;
        $info = $diff = [];
        for ($i = 1; $i <= $stage; ++$i) {
            list($monthMoney, $interestMoney) = static::capitalInfo($money, $monthRate, $capitalMoney, $i);
            $i == 1 && $firstMoney = (string)$monthMoney;
            $total += $monthMoney;
            $interestTotal += $interestMoney;
            $info[] = [
                'stage'           => (string)$i, // 期数
                'month_money'     => money_mil($monthMoney), // 月供总额
                'capital_money'   => money_mil($capitalMoney), // 月供本金
                'interest_money'  => money_mil($interestMoney), // 月供利息
                'surplus_capital' => money_mil(round($money - $capitalMoney * $i, 2) <0 ? 0 : round($money - $capitalMoney * $i, 2)), // 剩余本金
            ];
            $i <= 2 && $diff[] = $monthMoney;
        }

        $total = (string)round($total / 10000, 2);
        $interestTotal = (string)round($interestTotal / 10000, 2);
        $diff = money_mil(round($diff[0] - $diff[1], 2));
        return compact('total', 'interestTotal', 'info', 'firstMoney', 'diff');
    }

    /**
     * 计算等额本息，每月应还：贷款、利息、本金
     * @param $money 贷款总额
     * @param $monthRate 月利率
     * @param $stage 总期数
     * @param $month 当前期数
     * @return array
     */
    public static function interestInfo($money, $monthRate, $stage, $month) {

        // 月利率的期数次方
        $stagePow = pow(1 + $monthRate, $stage);
        // 月利率的当前月减一次方
        $monthPow = pow(1 + $monthRate, $month - 1);

        // 每月应还贷款
        $monthMoney = round(($money * $monthRate * $stagePow) / ($stagePow - 1), 2);

        // 每月应还本金
        $capitalMoney = round($money * $monthRate * $monthPow / ($stagePow - 1), 2);

        // 每月应还利息
        $interestMoney = $monthMoney - $capitalMoney;
        //        $interestMoney = round($money * $monthRate * ($stagePow- $monthPow) / ($stagePow - 1), 2);

        return [$monthMoney, $interestMoney, $capitalMoney];
    }

    /**
     * 计算等额本金，每月应还：贷款、本金
     * @param $money 贷款总额
     * @param $monthRate 月利率
     * @param $capitalMoney 每月应还本金
     * @param $month 当前期数
     * @return array
     */
    public static function capitalInfo($money, $monthRate, $capitalMoney, $month) {

        // 已还本金
        $capitalMoneyTotal = $capitalMoney * ($month - 1);

        // 每月应还利息
        $interestMoney = round(($money - $capitalMoneyTotal) * $monthRate, 2);

        // 每月应还金额
        $monthMoney = round($capitalMoney + $interestMoney, 2);

        return [$monthMoney, $interestMoney];

    }

    /**
     * 月利率计算
     * @param $rate 年利率即基准利率
     * @return float|int
     */
    private static function monthRate($rate) {
        return $rate / 12;
    }

}